Websydian v6.1 online documentationOnline documentation - WebsydianExpress v3.5

Validation - WebsydianExpress Overview

Introduction

Version 3.5 of WebsydianExpress introduces significant changes to the validation patterns. This document is not relevant for earlier versions.

The validation is still done based on the definitions in the Plex model, but where earlier versions used  the standard meta validation functions provided by Plex, in the new version, we have ported the code in the meta functions to a new abstract function (ValidationShellForProcess). This has allowed us to introduce options for customizing the validation and its output.

The messages from the validation can be implemented either using message log messages or by using text messages. This means that language support are also available for these messages.

ValidationShellForProcess

Overview

This section introduces the basic validation functionality that is implemented in the abstract ValidationShell function.

When using functions that inherit from ValidationShellForProcess you must have the WebsydianExpress runtime and database available.

The validation is performed for one variable, which is defined when implementing the function that inherits from the ValidationShellForProcess function. This variable can be an input, local, or output variable.

The subroutine that performs the validation is the "Main system validation" subroutine. This subroutine must be called after the values of the variable has been populated. Note that the abstract function does not call this subroutine. You have to do this yourself in the function that inherits from ValidationShellForProcess - or the validation will not be performed.

Functionality

ValidationShellForProcess basically performs 4 different validations - all are based on the standard Plex validation functions with minor modifications:

Field validated by

This validation is performed in the subroutine "Check field validated by".

The validation ensures that all the validation functions for the fields in the validation variable are called.

This validation is performed for all fields irrespective of whether they have been added to the variable by a view or as single fields. Fields that has been omitted from a view that has been added to the validation variable will not be handled.

 

Field relation validation

This validation is performed in the subroutine "Check field relations".

This checks the optionality restrictions from the the ENT known by FLD /ENT has FLD triples for the views that has been added to the validation variable.

This also calls any validation functions that has been defined for these triples.

 

Entity relation validation

This validation is performed in the subroutine "Check entity relations".

This checks the optionality for any ENT refers to ENT, ENT associated with ENT, ENT owned by ENT triples for the views that has been added to the validation variable.

This also calls any validation functions that has been defined for these triples

 

View validated by

This validation is performed in the subroutine "Check view validated by".

This calls any view validation functions defined for the views that has been added to the validation variable.

When an error has been registered, the function will create a message text and write it to the field Environment<*Message text>.

Depending on the function option UseMessageLog, this text will either be created as a message log message or as a message text.

If the message is written to the message log, the resulting message is added as a child to a main message that after the validation will scope all the messages reported by the validation. This is especially useful if you want to create a server function that can perform the validation and report all of the errors back to the calling function.

For each message that relates directly to one specific field (field validated by, field relation validation), the implementation name of the field will be added as a property to the message.

If the message is not written to the message log, the  the subroutine "Send message is called.

Afterwards, the validation will proceed. The base behavior of the function is to perform all validations - irrespective of the result of the previous validations. In this way, the function is able to report all errors at once.

After the validation has been performed, the field Environment<*Validation> contains the result of the validation.

This can be accessed in the edit point Handle system validation result - or at any time after the call to the "Main system validation" subroutine.

 

Note that if the option UseMessageLog is set, all the messages will be found in the message log. The messages will have the category "Validation" and the level "Informative". This means that you can use the message log to diagnose the errors encountered by the users.

Customizing

Edit points

One of the important aims of refactoring the validation patterns has been to make the validation more customizable. An important part of this has been to remove the validation from meta functions so that it has been possible to add edit points to the validation.

In all places, where a message has been created and written to Environment<*Message text>, an edit point has been added so that you can do any customizing or overriding of the messages you need in the exact spot where the error has been encountered.

Note that the message log / message texts are in fact created in this edit point (as this is an abstraction that builds on a very basic ValidationShell in the WSYVAL library).

Just before all calls to the Send message subroutine an edit point has been added. In this way, you can add your own handling/storing of specific messages at the point where they are reported.

Options

To make it easier to customize the functionality - and to build other abstract functions based on the ValidationShell, a number of options has been introduced.

These options are set or removed by FNC option NME triples.

CheckFldValidatedBy

Default: Yes

If this option is set to No, the FLD validated by FNC triples will not be handled.

CheckFldOptionality

Default: Yes

If this option is set to No, the optionality of the ENT has FLD / ENT known by FLD triples will not be checked.

CheckFldRelationValidatedBy

Default: Yes

If this option is set to No, the ENT has FLD / ENT known by FLD validation functions will not be called.

CheckEntityRelations

Default: Yes

If this option is set to No, the ENT refers to ENT / ENT associated with ENT / ENT owned by ENT triples will not be validated.

CheckViewValidatedBy

Default: Yes

If this option is set to No, the VW validated by FNC triples will not be handled.

SendMessage

Default: Yes

If this option is set to No, the Send message subroutine will not be called. This means that you will have to take control of storing and reporting the errors.

This option is mostly meant for use in other abstract functions.

UseMessageLog

Default: Yes

If this option is set to No, the messages will not be written to the message log. Instead, the messages will be created as message texts.

Change or translate message texts

The text of the message log messages / message texts can be maintained using the administration interface (Language support → Texts and messages).

Note that the message wont be available until it has been thrown the first time.

Replacing messages

The message log messages used by the ValidationShellForProcess can be found scoped by the functions WSYAPI/SystemAPI.ValidationMessages and WSYAPI/SystemAPI.ValidationTexts. You can change the messages by creating your own functions and replace the relevant CreateLogMessage / CreateTextMessage function on the function that inherits from ValidationShellForProcess. Unless you need to add parameters to the message, you should just change the text of the existing message using the administration interface instead.

Implementing

Inherit from ValidationShellForProcess
Source Object Verb Target Object
MyFunction is a FNC WSYAPI/ValidationShellForProcess
Define the variable to validate

In the subroutine "Main system validation" - edit point "Set +ValidationVariable":

Define the variable you want to validate and assign it to the meta variable +ValidationVariable.

Example (this function will validate the content of MyVariable):

 

+++Define Variable: MyVariable
+++Set Value Field: +ValidationVariable, Variable: MyVariable
 

Call the validation subroutine

In the point in your function where you want to perform the validation, call the validation subroutine. This must be done after content of the variable has been populated.

 

Go Sub Main system validation

Handle the validation result

You can access the result of the validation in the field Environment<*Validation>. This field will be available in the subroutine "Main system validation" - edit point "Handle system validation result".

EventHandlerForProcess

Overview

This is the existing EventHandlerForProcess, but inheritance from ValidationShellForProcess has been added.

The default behavior of the EventHandlerForProcess will be to use the old validation - as anything else would mean that all existing functions would have to be retested when upgrading to this version.

By setting the option UseNewValidation, you can instruct the EventHandler to use the new validation.

The function will validate the content of the Webinput variable. The default behavior is to validate all fields in the Webinput variable, but by setting the option ValidateHiddenFields to No, you can ensure that the fields specific validation isn't performed for these fields.

Functionality

This is based on the ValidationShellForProcess function. The functionality is the same as the one described above, with the following changes.

Validation variable

The validation variable is set to WebInput

Call of the validation subroutine

The "Main system validation" subroutine is called from the existing "Field and relation validation" subroutine. This will only be called if the UseNewValidation option is set.

If you have undefined the "Field and relation validation" subroutine to avoid the existing validation, this call will not be made.

Options

In addition to the options defined for the ValidationShellForProcess function, the following options are available:

UseNewValidation

Default: No

When this is No, the options CheckFldValidatedBy, CheckFldOptionality, CheckFldRelationValidatedBy, CheckEntityRelations. CheckViewValidatedBy are automatically set to No. This means that no code will be generated for the new validation.

Set this option to use the new validation functionality and to disable the old.

ValidateHiddenFields

Default: Yes

Set this to No if you do not want to validate the hidden fields (the fields in the local variable Hidden). Note that this will only influence the field related validation - not the relation and view validation.

ValidationEnabled

Default: No

Unless this is set to Yes, no validation (new or old) will be performed.

This is an option that has been introduced in an earlier version.

Implementing

Inherit from EventHandlerWithValidation
Source Object Verb Target Object
MyFunction is a FNC WSYAPI/EventHandlerForProcess
MyFunction option NME

...value SYS

UseNewValidation

Yes

Upgrade Considerations

The EventHandlerForProcess is an existing abstract function and as such, you should be aware that functionality has been added to the function.

However, the default behavior of the function will not change unless you set the option UseNewValidation.

Unless you want to implement the new validation functionality, you do not have to do anything when upgrading.

New abstract functions for validation outside the EventHandler

Overview

In the current implementation of the validation in the Websydian/WebsydianExpress patterns, the validation has always been performed in the EventHandler itself. This has some obvious practical advantages - primarily that the function can use the Send message subroutine to make the messages available for the PageGenerator.

However, having the validation implemented in the EventHandler itself has it owns problems:

1. The validation can only be tested by calling the EventHandler. This means that the web application has to be in place before you can test the validation.

2. When the validation is implemented in the EventHandler itself, it can't be called from other functions (or even from other EventHandlers). This means that you risk having the same validation implemented in many different functions - even if all the validation is made by using the Plex definitions, the question of when each function has been generated and built means that the different functions can perform different validation.

3. Each check performed in the validation can in some variants mean that a connection is made from the application server (the server where the EventHandler is deployed) to the database server. In the cases, where this is not the same server, this can carry a significant overhead.

This section describes the abstract functions that can help you developing validation functions for your application and how to ensure that they are called in your EventHandlers.

WSYAPI/Abstract.EventHandlerValidationFunction

This is the EventHandler you should inherit from when you want to implement an EventHandler that uses a separate validation function.

The option ValidationEnabled is set to No (as the validation should not be performed in the EventHandler itself).

The function calls a function WSYAPI/Abstract.ValidationFunction in the edit point Process Input. To create your own validation function, let it inherit from the abstract function and replace the function on the EventHandler.

WSYAPI/Abstract.ValidationFunction

This is the function that will be used to perform the validation. The function has an input variable WebInputData. The function will validate the content of this variable.

If any errors has been found, the function will return an error code in the returning status. This error codes specifies a message in the message log. The messages thrown by the validation will be found as child messages to this message.

Note that the TransactionValidation function doesn't inherit from WSYAPI/Abstract.WebServerExternal - this is because you in some cases might want to split the validation out in a separate function - but still let it be executed on the server where you run the EventHandler/PageGenerators (this is always a necessity if you have the WebsydianExpress database and the application database on separate servers).

Using the message log in your own validation functions

This is only relevant if you have UseMessageLog set to Yes (default) for the validation function.

In some cases, you will define functions that will be called as part of the validation - e.g. the functions specified by FLD validated by FNC / VW validated by FNC.

The "normal" validation functions will just return *Error in the returned status. The reaction of the calling function is to create a generic message that just states that there is something wrong with the field.

By using the message log to store the validation messages you get the option to create specific messages for each error situation in the validated by functions and to report them back to the calling function, which will in this case not create a generic error message it will just add the reported message to the main validation message.

Implementing - example

This example will show how you can create a server side validation function for an entity MyEntity and an EventHandler that calls this validation function.

Create Validation Function
Source Object Verb Target Object
MyValidationFunction is a FNC WSYAPI/Abstract.ValidationFunction
MyValidationFunction input view VW

...for VAR

MyEntity.Update

WebInputData

MyValidationFunction implement SYS Yes
Create EventHandler
Source Object Verb Target Object
MyEventHandler is a FNC WSYAPI/Abstract.EventHandlerValidationFunction
MyEventHandler local view VW

...for VAR

MyEntity.Update

WebInput

MyEventHandler replaces FNC

...by FNC

WSYAPI/Abstract.ValidationFunction

MyValidationFunction

MyEventHandler implement SYS Yes

The default behavior of the validation function is to use the message log as a store for the messages reported by the validation and that the error page specified for the EventHandler is called if the validation reports an error. If this is the behavior you want, you do not have to do anything else to implement the validation. 

The following information is relevant if you want to have your own handling of the result of the validation.

MyValidationFunction has two dual fields: MainMessageID and InstanceValid.

After the call, the MainMessageID will contain the identification of the error message that scopes the messages reported by the validation.

The InstanceValid field indicates whether the validation has been successful. Note that this field is mapped with the local field WsyBase<InstanceValid>, which is used to determine the behavior of the EventHandler after the validation has been performed.

Implementing a Field/View/Field relation "validated by" function using message log messages

For each error situation you want to handle in the function, create a function:

MyLogMessage is a WSYAPI/Abstract.CreateValidationLogMessage

Create the validated by function as usual.

When you encounter an error in the validated by function, call the appropriate log message function. Set the Environment<*Returning status> to the message id returned by the log message function.

The calling validation function will check whether the value in the returned status is a message id - if it is it will add the message to the main message for the validation.

Letting the validation function return multiple messages

The normal validation functions just return error or success, as described just above, you can use the message log to return a more specific message about the error - with one extra step you also have the capability to let the validation function return a set of messages.

To do so, you will have to create one more function that inherits from WSYAPI/Abstract.CreateValidationLogMessage. Just as the calling validation function has a main message to which all the relevant messages for the validation are added as child messages, this message will be the main message for the validated by function.

Specify a message like "Error from validation of field &(1:)" in the message text for this message. When you encounter the first error in the validation function, start by calling this message and assign the value returned by it to the Environment<*Returning status> field.

Then call the relevant log message function for the specific error and add it as a child to this message.

For each error encountered afterwards, just add the resulting message as s child.

In the end the validation function will return a message that contain a number of messages, this message will be added to the main message of the validation function. In this way a tree-structure with three levels will be created.

Changes to Error Pages

The normal behavior of the error pages has been that the EventHandler has written the messages to memory, the PageGenerator is called by the EventHandler and so it can read the messages from memory and show them in a gird.

As the default for the new validation is that the messages are stored as WebsydianExpress message log messages, functionality to show these messages has been added to the existing WebsydianExpress error pages.

The identification of the main WebsydianExpress message (that scopes all the messages from the validation) is written to memory by the EventHandler. The information is read by the PageGenerator (it populates the local field InputByMemory<APIFields.MainMessageID>). After reading and showing all the "old" style messages from memory, all child messages for the main messages are read and shown in the grid.

So in this way, all messages are shown, no matter which method has been used to transfer them from the EventHandler to the error page.

Abstract message log / message text functions

Abstract.CreateValidationLogMessage

This function can be used as the ancestor of any custom validation log messages you want to create. The messages will get the level "Informative" and the message category "Validation".

Abstract.CreateValidationTextMessage

This function can be used as the ancestor of any custom validation text messages you want to create. The message types will get the category "Validation".